package org.gdstash.db;

import org.gdstash.util.GDMsgFormatter;
import org.gdstash.util.GDMsgLogger;

import java.sql.*;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

public class DBItemCraft {
    private static final String TABLE_NAME = "GD_ITEM_CRAFT";
    private static final String FIELD_ID = "ITEM_ID";
    private static final int ROW_ITEM_ID = 1;
    private static final int ROW_CRAFT_ID = 2;
    private static ConcurrentHashMap<String, DBItemCraft> hashBuffer;
    private String itemID;
    private String craftID;

    static {
        DBItemCraft.hashBuffer = new ConcurrentHashMap<String, DBItemCraft>();
    }

    public String getItemID() {
        return this.itemID;
    }

    public void setItemID(final String itemID) {
        this.itemID = itemID;
    }

    public String getCraftID() {
        return this.craftID;
    }

    public static void clearBuffer() {
        DBItemCraft.hashBuffer.clear();
    }

    public static void createTables(final Connection conn) throws SQLException {
        final String dropTable = "DROP TABLE GD_ITEM_CRAFT";
        final String createTable = "CREATE TABLE GD_ITEM_CRAFT (ITEM_ID VARCHAR(256) NOT NULL, CRAFT_ID     VARCHAR(256), PRIMARY KEY (ITEM_ID))";
        try (final Statement st = conn.createStatement()) {
            if (GDDBUtil.tableExists(conn, "GD_ITEM_CRAFT")) {
                st.execute(dropTable);
            }
            st.execute(createTable);
            st.close();
            conn.commit();
        } catch (SQLException ex) {
            conn.rollback();
            final Object[] args = {"GD_ITEM_CRAFT"};
            final String msg = GDMsgFormatter.format(GDMsgFormatter.rbMsg, "ERR_CREATE_TABLE", args);
            GDMsgLogger.addError(msg);
            throw ex;
        }
    }

    public static void delete(final Connection conn, final String itemID) throws SQLException {
        final String deleteEntry = "DELETE FROM GD_ITEM_CRAFT WHERE ITEM_ID = ?";
        try (final PreparedStatement ps = conn.prepareStatement(deleteEntry)) {
            ps.setString(1, itemID);
            ps.executeUpdate();
            ps.close();
        } catch (SQLException ex) {
            throw ex;
        }
    }

    public static void insert(final Connection conn, final DBItem dbItem) throws SQLException {
        final String insertItem = "INSERT INTO GD_ITEM_CRAFT VALUES (?,?)";
        try (final PreparedStatement ps = conn.prepareStatement(insertItem)) {
            ps.setString(1, dbItem.getItemID());
            ps.setString(2, dbItem.getCraftID());
            ps.executeUpdate();
            ps.close();
            conn.commit();
        } catch (SQLException ex) {
            conn.rollback();
            final Object[] args = {dbItem.getItemID(), "GD_ITEM_CRAFT"};
            final String msg = GDMsgFormatter.format(GDMsgFormatter.rbMsg, "ERR_INS_TABLE_BY_ID", args);
            GDMsgLogger.addLowError(msg);
            GDMsgLogger.addLowError(ex);
        }
    }

    public static DBItemCraft get(final String itemID) {
        DBItemCraft craft = null;
        craft = DBItemCraft.hashBuffer.get(itemID);
        if (craft == null) {
            craft = getDB(itemID);
        }
        return craft;
    }

    private static DBItemCraft getDB(final String itemID) {
        DBItemCraft craft = null;
        final String command = "SELECT * FROM GD_ITEM_CRAFT WHERE ITEM_ID = ?";
        try (final Connection conn = GDDBData.getConnection();
             final PreparedStatement ps = conn.prepareStatement(command)) {
            ps.setString(1, itemID);
            try (final ResultSet rs = ps.executeQuery()) {
                final List<DBItemCraft> list = wrap(rs);
                if (list.isEmpty()) {
                    craft = null;
                } else {
                    craft = list.get(0);
                }
                conn.commit();
            } catch (SQLException ex) {
                throw ex;
            }
        } catch (SQLException ex2) {
            final Object[] args = {itemID, "GD_ITEM_CRAFT"};
            final String msg = GDMsgFormatter.format(GDMsgFormatter.rbMsg, "ERR_READ_TABLE_BY_ID", args);
            GDMsgLogger.addError(msg);
            GDMsgLogger.addError(ex2);
        }
        return craft;
    }

    public static List<DBItemCraft> getByItemIDs(final List<String> itemIDs) {
        final List<DBItemCraft> list = new LinkedList<DBItemCraft>();
        for (final String itemID : itemIDs) {
            final DBItemCraft craft = get(itemID);
            list.add(craft);
        }
        return list;
    }

    public static DBItemCraft getByCraftID(final String itemID) {
        DBItemCraft craft = null;
        final String command = "SELECT * FROM GD_ITEM_CRAFT WHERE CRAFT_ID = ?";
        try (final Connection conn = GDDBData.getConnection();
             final PreparedStatement ps = conn.prepareStatement(command)) {
            ps.setString(1, itemID);
            try (final ResultSet rs = ps.executeQuery()) {
                final List<DBItemCraft> list = wrap(rs);
                if (list.isEmpty()) {
                    craft = null;
                } else {
                    craft = list.get(0);
                }
                conn.commit();
            } catch (SQLException ex) {
                throw ex;
            }
        } catch (SQLException ex2) {
            final Object[] args = {itemID, "GD_ITEM_CRAFT"};
            final String msg = GDMsgFormatter.format(GDMsgFormatter.rbMsg, "ERR_READ_TABLE_BY_ID", args);
            GDMsgLogger.addError(msg);
            GDMsgLogger.addError(ex2);
        }
        return craft;
    }

    public static boolean isCraftableItemID(final String itemID) {
        final List<DBItemCraft> crafts = null;
        boolean craftable = false;
        final String command = "SELECT * FROM GD_ITEM_CRAFT WHERE CRAFT_ID = ?";
        try (final Connection conn = GDDBData.getConnection();
             final PreparedStatement ps = conn.prepareStatement(command)) {
            ps.setString(1, itemID);
            try (final ResultSet rs = ps.executeQuery()) {
                if (rs.next()) {
                    craftable = true;
                }
                conn.commit();
            } catch (SQLException ex) {
                craftable = false;
                throw ex;
            }
        } catch (SQLException ex2) {
            final Object[] args = {itemID, "GD_ITEM_CRAFT"};
            final String msg = GDMsgFormatter.format(GDMsgFormatter.rbMsg, "ERR_READ_TABLE_BY_ID", args);
            GDMsgLogger.addError(msg);
            GDMsgLogger.addError(ex2);
        }
        return craftable;
    }

    private static List<DBItemCraft> wrap(final ResultSet rs) throws SQLException {
        final LinkedList<DBItemCraft> list = new LinkedList<DBItemCraft>();
        while (rs.next()) {
            final DBItemCraft craft = new DBItemCraft();
            craft.itemID = rs.getString(1);
            craft.craftID = rs.getString(2);
            list.add(craft);
            DBItemCraft.hashBuffer.put(craft.itemID, craft);
        }
        return list;
    }

    public void setCraftID(final String craftID) {
        this.craftID = craftID;
    }
}
